         #include<linux/module.h>
        #include<linux/kernel.h>
        #include<linux/init.h>
        #include<linux/types.h>
        #include<linux/slab.h>
        #include<linux/string.h>
        #include<linux/input.h>
        #include<linux/irq.h>
        #include<mach/gpio.h>
        #include<mach/regs-gpio.h>
        #include<asm/irq.h>
        #include<asm/io.h>
        #include<linux/interrupt.h>
        #include<linux/delay.h>

        #define DEVICE_NAME    "TQ2440_BUTTON"

        #define NUMBERS_BUTTONS        4

        static const char * input_name = "Tq2440_button";

        static struct input_dev *button_dev;

        /*中断集合*/
        static const int irqs[NUMBERS_BUTTONS]={
            IRQ_EINT0,
            IRQ_EINT2,
            IRQ_EINT11,
            IRQ_EINT19,
        };

        /*端口集合*/
        static const int gpios[NUMBERS_BUTTONS]={
            S3C2410_GPF(0),
            S3C2410_GPF(2),
            S3C2410_GPG(3),
            S3C2410_GPG(11),
        };
        /*事件代号集合*/
        static const int keys[NUMBERS_BUTTONS]={
            KEY_1,
            KEY_2,
            KEY_3,
            KEY_4,
        };

        /*中断处理程序*/

        static irqreturn_t button_interrupt(int irq,void * p)
        {
            int val = 0, i= 0;
            for(i = 0; i < NUMBERS_BUTTONS; ++ i)
            {
                /*如果中断号正确*/
               
                if(irqs[i] == irq)
                {
                    /*读取端口的值*/
                   
                    val = s3c2410_gpio_getpin(gpios[i]);
                    /*汇报端口的值，实质上是将事件key[i]汇报*/
                   
                    input_report_key(button_dev,keys[i],val);
                    /*汇报同步，也就是完成汇报工作*/
                   
                    input_sync(button_dev);
                    break;
                }   
            }
            /*返回值*/
           
            return IRQ_RETVAL(IRQ_HANDLED);
        }

        /*设备初始化函数*/

        static int __init tq2440_button_init(void)
        {
            int err,i = 0;
            /*主要要先申请设备，然后申请中断*/
           
            /*申请输入设备*/
            button_dev = input_allocate_device();
           
            if(NULL == button_dev)
            {
                printk(KERN_ERR "not enough memory\n");
                err = - ENOMEM;
            }
           
            /*设置相应的事件处理类型,按键事件*/
            set_bit(EV_KEY,button_dev->evbit);

            /*申请中断*/
            for(i = 0; i < NUMBERS_BUTTONS; ++ i)
            {
                /*申请中断*/
                request_irq(irqs[i],button_interrupt,IRQ_TYPE_EDGE_BOTH,
                    DEVICE_NAME,NULL);
                /*设置案件的代码值,即code值*/
                set_bit(keys[i],button_dev->keybit);
            }
               
            /*设备名，防止出现错误*/
            button_dev->name = input_name;   
           
            /*注册输入设备*/
            err = input_register_device(button_dev);
           
            if(err)
            {
                printk(KERN_ERR "failed to register device\n");
               
                goto err_free_dev;
            }
           
            printk("initialized\n");

            return 0;

        /*错误处理*/
        err_free_dev:
            /*注销设备*/
            input_unregister_device(button_dev);
            return err;
        }

        /*设备退出函数*/
        static void __exit tq2440_button_exit(void)
        {
            int i = 0;
            input_unregister_device(button_dev);

            /*释放中断号*/
            for(i = 0; i < NUMBERS_BUTTONS; ++ i)
            {
                free_irq(irqs[i],NULL);
            }
        }

        /*加载和卸载*/
        module_init(tq2440_button_init);
        module_exit(tq2440_button_exit);

        /*LICENSE和作者信息*/
        MODULE_LICENSE("GPL");
